/*************************************************************************
    > File Name: rd905uw.cpp
    > Author: Jintao Yang
    > Mail: 18608842770@163.com 
    > Created Time: 2021年07月01日 星期四 14时47分01秒
 ************************************************************************/

#include "rd905uw.h"
#include <unistd.h>
#include <pthread.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

using namespace std;

rd905uw::rd905uw()
{
    this->m_serial = new serial::Serial();
	//serial::Timeout timeout = serial::Timeout::simpleTimeout(1000);
	this->m_serial->setTimeout(1000, 40, 0, 40, 0);
}

rd905uw::~rd905uw()
{
	if (NULL != this->m_serial)
	{
        if (this->m_serial->isOpen())
        {
            this->m_serial->close();
            printf("close m_serial!\n");
        }

        printf("free m_serial!\n");
		delete this->m_serial;
		this->m_serial = NULL;
	}
}

unsigned int rd905uw::crc16(unsigned char const* PucY, unsigned char UcX)
{
	unsigned short int  uiCrcValue = 0xFFFF;

	for (unsigned char ucI = 0; ucI < UcX; ucI++)
	{
		uiCrcValue = uiCrcValue ^ *(PucY + ucI);
		for (unsigned char ucJ = 0; ucJ < 8; ucJ++)
		{
			if (uiCrcValue & 0x0001)
			{
				uiCrcValue = (uiCrcValue >> 1) ^ 0x8408;
			}
			else
			{
				uiCrcValue = (uiCrcValue >> 1);
			}
		}
	}

	return uiCrcValue;
}

int rd905uw::querryEPC(char *szEPC)
{
    int iLen = 0;
    pthread_mutex_trylock(&mutex);

    try
    {
		unsigned char req_epc[5] = {0x04, 0x00, 0x01};
		unsigned int crcVal = crc16(req_epc, 3);
		req_epc[3] = (unsigned char)(crcVal & 0x00ff);
		req_epc[4] = (unsigned char)((crcVal & 0xff00) >> 8);
        size_t bytes_wrote = this->m_serial->write(req_epc, 5);
        usleep(10);
        if (bytes_wrote > 0)
        {
            uint8_t result[32] = "\0";
            memset(result, 0, sizeof(result));
            size_t r_size = this->m_serial->read(result, 20);

            if (r_size == 20 && result[0] == 0x13 && result[1] == 0x00 && result[2] == 0x01 && result[3] == 0x01 && result[4] == 0x01 && result[5] == 0x0c )
            {
                iLen = r_size;
                char byteStr[8] = {0};
                string rfidStr;
                for (size_t i = 0; i < 12; ++i)
                {
                    sprintf(byteStr, "%x", result[i + 6]);
                    if (strlen(byteStr) == 1)
                    {
                        rfidStr.append("0");
                    }
                    rfidStr.append(byteStr);
                }
                memcpy(szEPC, rfidStr.c_str(), 24);

                printf("rfid EPC %s\n", szEPC);
            }
        }
    }
    catch (exception &e)
    {
		printf("Unhandled Exception: %s\n", e.what());
	}
    pthread_mutex_unlock(&mutex);
    
    return iLen;
}

int rd905uw::querryTID(char *szTID)
{
    int iLen = 0;
    pthread_mutex_trylock(&mutex);

    try
    {
        unsigned char req_tid[7] = {0x06, 0x00, 0x01, 0x00, 0x06};
		unsigned int crcVal = crc16(req_tid, 5);
		req_tid[5] = (unsigned char)(crcVal & 0x00ff);
		req_tid[6] = (unsigned char)((crcVal & 0xff00) >> 8);
        size_t bytes_wrote = this->m_serial->write(req_tid, 7);
        usleep(10);
        if (bytes_wrote > 0)
        {
            uint8_t result[32] = "\0";
            memset(result, 0, sizeof(result));
            size_t r_size = this->m_serial->read(result, 20);

            if (r_size == 20 && result[0] == 0x13 && result[1] == 0x00 && result[2] == 0x01 && result[3] == 0x01 && result[4] == 0x01 && result[5] == 0x0c )
            {
                iLen = r_size;
                char byteStr[8] = {0};
                string rfidStr;
                for (size_t i = 0; i < 12; ++i)
                {
                    sprintf(byteStr, "%x", result[i + 6]);
                    if (strlen(byteStr) == 1)
                    {
                        rfidStr.append("0");
                    }
                    rfidStr.append(byteStr);
                }
                memcpy(szTID, rfidStr.c_str(), 24);

                printf("rfid TID %s\n", szTID);
            }
        }
    }
    catch (exception &e)
    {
		printf("Unhandled Exception: %s\n", e.what());
	}
    pthread_mutex_unlock(&mutex);

    return iLen;
}

int rd905uw::open_device(const std::string &szPort, uint32_t iBaud)
{
    int ret = 0;
    
    try
    {
        this->m_serial->setPort(std::string(szPort));
        this->m_serial->setBaudrate(iBaud);
        this->m_serial->open();
    }
    catch (exception &e)
	{
		printf("Unhandled Exception: %s\n", e.what());
	}

    return ret;
}

int rd905uw::close_device()
{
    if (this->m_serial->isOpen())
    {
        printf("Port is open!\n");

        try
        {
            this->m_serial->close();
            printf("Close ...\n");
        }
        catch (exception &e)
        {
            printf("Unhandled Exception: %s\n", e.what());
        }

        if (this->m_serial->isOpen())
        {
            printf("Close port failed!\n");
            return -1;
        }
    }
    printf("Close port succeed!\n");

    return 0;
}
